// serialize
package socks

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"hash/crc32"
	"log"
	"reflect"
	"sync"
	"unsafe"
)

const cMaxArrSize = 0xFFFFFF

type fieldInfo struct {
	offset     uintptr
	size       uint32 // 大小，0 为动态大小需要计算，切片，字符串等
	kind       reflect.Kind
	arrLen     uint32       // 数组长度，只有数组才有
	elemKind   reflect.Kind // 数组和切片的元素类型
	elemType   reflect.Type // 创建切片的时候要用到
	elemSize   uint32       // 单个元素的大小，只有切片会用到
	tp         reflect.Type // 当前字段的类型，创建切片要用到
	structInfo *typeInfo    // 如果是结构体就指向结构信息
}

type typeInfo struct {
	id        HashIdType
	fields    []fieldInfo // 所有字段
	tp        reflect.Type
	dynFields []fieldInfo // 动态大小的字段，如：切片、字符串等
	fixedSize uint32      // 固定字段的大小，计算长度只用计算动态字段的长度
	crc32     uint32      // 可以识别出字段是否兼容
}

type HashIdType = int32 // =, 用别名，方便兼容
type typeIdHash map[HashIdType]*typeInfo
type typeHash map[reflect.Type]*typeInfo

type Serializer struct {
	typeHashTable typeHash
	idHashTable   typeIdHash
	isLikeCRecord bool         // 是否跟C++ Record 兼容的方式
	mu            sync.RWMutex // 读写锁
}

// 方便线程和不同的模式使用 isLikeCStruct 主要是跟 c++、Delphi 类通讯
func NewSerializer(isLikeCStruct bool, hashTblSize int) *Serializer {
	ret := new(Serializer)
	ret.idHashTable = make(typeIdHash, hashTblSize)
	ret.typeHashTable = make(typeHash, hashTblSize)
	ret.isLikeCRecord = isLikeCStruct
	return ret
}

// 是否为固定大小的类型
func isFixedSizeKind(kind reflect.Kind) bool {
	ret := false
	if (kind >= reflect.Bool) && (kind <= reflect.Complex128) {
		ret = true
	}
	return ret
}

type emptyInterface struct {
	typ  *struct{}
	word uintptr
}

func GetValueDataPtr(v *reflect.Value) uintptr {
	return (*(*emptyInterface)(unsafe.Pointer(v))).word
}

func (s *Serializer) addType(id HashIdType, tpInfo *typeInfo) bool {
	s.mu.Lock()
	defer s.mu.Unlock()
	if id > 0 {
		s.idHashTable[id] = tpInfo
	}
	s.typeHashTable[tpInfo.tp] = tpInfo
	return true
}

func (s *Serializer) idIsExists(id HashIdType) bool {
	s.mu.RLock()
	defer s.mu.RUnlock()
	_, ok := s.idHashTable[id]
	return ok
}

func (s *Serializer) regType(id HashIdType, tp reflect.Type) *typeInfo {

	//log.Println("type.kind = ", tp.Kind(), tp.Name())

	tpInfo := new(typeInfo)
	tpInfo.tp = tp
	tpInfo.id = id

	fldCnt := tp.NumField()
	buff := bytes.NewBuffer(nil)
	binary.Write(buff, binary.LittleEndian, uint16(fldCnt))

	// log.Println("type.kind = ", tp.Kind(), tp.Name(), fldCnt)

	for i := 0; i < fldCnt; i++ {
		fld := tp.Field(i)
		fldInfo := fieldInfo{} // 清空
		fldInfo.offset = fld.Offset
		fldInfo.kind = fld.Type.Kind()
		fldInfo.tp = fld.Type

		binary.Write(buff, binary.LittleEndian, uint8(fldInfo.kind))

		// log.Println("regType: ", i, tp, fld.Type.Kind(), fld.Type, uint8(fldInfo.kind))

		if isFixedSizeKind(fldInfo.kind) {
			fldInfo.size = uint32(fld.Type.Size()) // 可以直接 copy
		} else {
			switch fldInfo.kind {
			case reflect.Array, reflect.Slice:
				fldInfo.elemType = fld.Type.Elem()
				fldInfo.elemKind = fldInfo.elemType.Kind()
				binary.Write(buff, binary.LittleEndian, uint32(fldInfo.elemKind)) // 写入元素类型
				if isFixedSizeKind(fldInfo.elemKind) {
					fldInfo.elemSize = uint32(fldInfo.elemType.Size())
				}

				if fldInfo.kind == reflect.Array {
					fldInfo.arrLen = uint32(fld.Type.Len())
					binary.Write(buff, binary.LittleEndian, fldInfo.arrLen) // 数组还要写入长度
					if isFixedSizeKind(fldInfo.elemKind) {
						fldInfo.size = uint32(fld.Type.Size())
					}
				}

			case reflect.String:
				fldInfo.size = 0

			case reflect.Struct:
				sTpInfo, _ := s.tryGetTypeInfo(fld.Type)
				if sTpInfo == nil { // 没找到，直接注册
					sTpInfo = s.regType(0, fld.Type)
				}
				fldInfo.structInfo = sTpInfo

				binary.Write(buff, binary.LittleEndian, sTpInfo.crc32) // 结构直接写入crc，子结构变了，本结构也会跟着变，类似区块链

				//log.Println("注册结构体: ", *sTpInfo)

			default:
				log.Panicln("不支持的字段类型，注册失败 ", fldInfo.kind, fld)
				return nil
			}
		}

		if fldInfo.size == 0 {
			tpInfo.dynFields = append(tpInfo.dynFields, fldInfo) // 请加动态字段
		} else {
			tpInfo.fixedSize += fldInfo.size // 累加固定大小
		}

		// log.Println("regType: append ", tp, i, fldInfo.tp, fldInfo.kind)
		tpInfo.fields = append(tpInfo.fields, fldInfo)
	}
	// log.Println("regType: crcbits = ", buff.Bytes())
	tpInfo.crc32 = crc32.ChecksumIEEE(buff.Bytes())
	// log.Println("regType: tpinfo = ", tp, ", crc32 = ", tpInfo.crc32)
	s.addType(id, tpInfo)
	return tpInfo
}

func (s *Serializer) RegisterType(id HashIdType, obj interface{}) bool {
	if s.idIsExists(id) {
		log.Println("id 重复: ", id)
		return false
	}

	tp := reflect.TypeOf(obj)
	if tp.Kind() == reflect.Ptr {
		tp = tp.Elem()
	}

	return s.regType(id, tp) != nil
}

const (
	cUint16Tag     uint8  = 254
	cUint32Tag     uint8  = 255
	cCRC32Size            = uint32(unsafe.Sizeof(uint32(0)))
	cMinHeaderSize        = cCRC32Size + 1
	cMaxUint16     uint32 = 0xFFFF
)

func GetLengthDataLen(avLen uint32) uint32 {
	if avLen < uint32(cUint16Tag) {
		return 1
	} else if avLen <= cMaxUint16 {
		return 3
	} else {
		return 5
	}
}

func WiriteLength(bits []byte, aLength uint32) (wirteLen uint32) {
	arrLen := len(bits)
	if (arrLen >= 1) && (aLength < uint32(cUint16Tag)) {
		bits[0] = uint8(aLength)
		return 1
	} else if (arrLen >= 3) && (aLength <= cMaxUint16) {
		bits[0] = cUint16Tag
		*(*uint16)(unsafe.Pointer(&bits[1])) = uint16(aLength)
		return 3
	} else if arrLen >= 5 {
		bits[0] = cUint32Tag
		*(*uint32)(unsafe.Pointer(&bits[1])) = aLength
		return 5
	}
	return 0 // 写入失败
}

// 获取字符串的写入长度
func getStringWriteLen(str string) uint32 {
	l := uint32(len(str))
	return l + GetLengthDataLen(l)
}

const cMove16 = uint32(16)
const cMove4 = uint32(4)

func Move(src, dst uintptr, size uint32) {
	if (src == dst) || (size == 0) {
		return
	}

	ps := PByteArray(unsafe.Pointer(src))
	pd := PByteArray(unsafe.Pointer(dst))

	if (src < dst) && (src+uintptr(size) > dst) { // 两块内存有重叠，从左向右复制，要反向操作，先复制尾部的
		dis := uint32(dst - src) // 这个速度慢点，但能保证结果正确
		idx := size
		if (dis >= cMove16) && (idx >= cMove16) {
			for {
				idx -= cMove16
				*(*complex128)(unsafe.Pointer(&(*pd)[idx])) = *(*complex128)(unsafe.Pointer(&(*ps)[idx]))
				if idx < cMove16 {
					break
				}
			}
		}

		if (dis >= cMove4) && (idx >= cMove4) {
			for {
				idx -= cMove4
				*(*uint32)(unsafe.Pointer(&(*pd)[idx])) = *(*uint32)(unsafe.Pointer(&(*ps)[idx]))
				if idx < cMove4 {
					break
				}
			}
		}

		for i := int(idx) - 1; i >= 0; i-- {
			(*pd)[i] = (*ps)[i]
		}
	} else {
		copy((*pd)[0:size], (*ps)[0:size])
	}

}

func CopyMemory(src, dst []byte) int {
	l := len(src)
	l2 := len(dst)
	if l2 < l {
		l = l2
	}
	Move(uintptr(unsafe.Pointer(&src[0])), uintptr(unsafe.Pointer(&dst[0])), uint32(l))
	return l
}

func ReadLength(bits []byte) (lengthValue uint32, readLen uint32) {
	bitsLen := len(bits)
	if bitsLen >= 1 {
		var v uint8 = bits[0]
		if v < cUint16Tag {
			return uint32(v), 1
		} else if (bitsLen >= 3) && (v == cUint16Tag) {
			v16 := *(*uint16)(unsafe.Pointer(&bits[1]))
			return uint32(v16), 3
		} else if bitsLen >= 5 {
			v32 := *(*uint32)(unsafe.Pointer(&bits[1]))
			return v32, 5
		}
	}
	return 0, 0
}

func ReadString(bits []byte) (str string, readLen uint32) {
	bitsLen := uint32(len(bits))
	sl, n := ReadLength(bits)
	if n > 0 {
		idx := uint32(0)
		idx += n
		if idx+sl <= bitsLen {
			str := string(bits[idx : idx+sl])
			return str, idx + sl
		} else {
			log.Println("读取失败内容长度不够", bitsLen, idx+sl)
		}

	} else {
		log.Println("读取字符串长度失败")
	}
	return "", 0
}

func WriteString(bits []byte, str string) (writeLen uint32) {
	bitsLen := uint32(len(bits))
	sl := uint32(len(str))
	idx := uint32(WiriteLength(bits, sl))

	if (sl > 0) && (idx+sl <= bitsLen) {
		ps := getSliceDataPtr(uintptr(unsafe.Pointer(&str)))
		pd := uintptr(unsafe.Pointer(&bits[idx]))
		Move(ps, pd, sl)
		idx += sl
	}

	return idx
}

func writeSlice(bits []byte, slicePtr uintptr, fld *fieldInfo) (writeLen uint32) {
	bitsLen := uint32(len(bits))
	sliceLen := getSliceLength(slicePtr)

	idx := WiriteLength(bits, uint32(sliceLen))
	if idx == 0 {
		log.Println("切片长度写入失败 ", sliceLen, bitsLen)
		return 0
	}
	if fld.elemSize > 0 { // 可以copy的类型
		size := uint32(sliceLen) * fld.elemSize
		if idx+size > bitsLen {
			log.Println("写入切片固定大小长度不足: ", idx+size, bitsLen)
			return 0
		}
		ps := getSliceDataPtr(slicePtr)
		Move(ps, uintptr(unsafe.Pointer(&bits[idx])), size)
		idx += size
	} else {
		switch fld.elemKind {
		case reflect.String:
			ps := (*[]string)(unsafe.Pointer(slicePtr))
			for i := 0; i < sliceLen; i++ {
				n := WriteString(bits[idx:], (*ps)[i])
				if n == 0 {
					log.Println("写入字符串切片失败: ", i, (*ps)[i])
					return 0
				}
				idx += n
			}
		default:
			log.Println("不支持的切片类型写入: ", fld.elemType)
			return 0
		}
	}
	return idx
}

func readSlice(bits []byte, slicePtr uintptr, fld *fieldInfo) uint32 {
	sliceLen, idx := ReadLength(bits)
	if idx == 0 {
		log.Println("读取切片长度失败: ", fld)
		return 0
	}

	bitsLen := len(bits)

	// 构造 slice 并赋值
	// fmt.Println("readSlice: elemType = ", fld.tp, sliceLen)
	v := reflect.MakeSlice(fld.tp, int(sliceLen), int(sliceLen))
	ps := (*reflect.SliceHeader)(unsafe.Pointer(GetValueDataPtr(&v)))
	*(*reflect.SliceHeader)(unsafe.Pointer(slicePtr)) = *ps

	if fld.elemSize > 0 { // 可以 copy 的类型
		size := fld.elemSize * sliceLen
		if size+idx > uint32(bitsLen) {
			log.Println("读取slice失败，数据长度不够", size+idx, bitsLen)
			return 0
		}
		pbs := PByteArray(unsafe.Pointer(ps.Data))
		copy(pbs[0:size], bits[idx:idx+size])
		idx += size
	} else {
		switch fld.elemKind {
		case reflect.String:
			pStrs := (PStrArray)(unsafe.Pointer(ps.Data))
			for i := 0; i < int(sliceLen); i++ {
				str, rLen := ReadString(bits[idx:])
				if rLen == 0 {
					log.Println("读取切片字符串失败: 长度不够 ", i, idx, bitsLen)
					return 0
				}
				(*pStrs)[i] = str
				idx += rLen
			}
		default:
			log.Println("不能支持的切片类型 read : ", fld.elemType)
		}
	}

	return idx
}

func readArray(bits []byte, arrPtr uintptr, fld *fieldInfo) (readLen uint32) {
	bitsLen := uint32(len(bits))
	idx := uint32(0)
	if fld.size > 0 { // 可以直接复制的类型
		if bitsLen >= fld.size {
			Move(uintptr(unsafe.Pointer(&bits[0])), arrPtr, fld.size)
			idx = fld.size
		} else {
			log.Println("readArray 读取固定大小失败，长度不够 ", fld.size, bitsLen)
			return 0
		}
	} else {
		switch fld.elemKind {
		case reflect.String:
			pStrs := PStrArray(unsafe.Pointer(arrPtr))
			for i := 0; i < int(fld.arrLen); i++ {
				str, n := ReadString(bits[idx:])
				if n == 0 {
					log.Println("读取字符串数组失败 ", i, idx)
					return 0
				}
				(*pStrs)[i] = str
				idx += n
			}
		default:
			log.Println("readArray 不技能的数组类型 ", fld.elemKind)
			return 0
		}
	}
	return idx
}

func writeArray(bits []byte, arrPtr uintptr, fld *fieldInfo) (writeLen uint32) {
	bitsLen := uint32(len(bits))
	idx := uint32(0)
	if fld.size > 0 { // 可以直接复制的类型
		if bitsLen >= fld.size {
			Move(arrPtr, uintptr(unsafe.Pointer(&bits[0])), fld.size)
			idx = fld.size
		} else {
			log.Println("writeArray 写入固定大小失败，长度不够 ", fld.size, bitsLen)
			return 0
		}
	} else {
		switch fld.elemKind {
		case reflect.String:
			pStrs := PStrArray(unsafe.Pointer(arrPtr))
			for i := 0; i < int(fld.arrLen); i++ {
				str := (*pStrs)[i]
				n := WriteString(bits[idx:], str)
				if n == 0 {
					log.Println("写入字符串数组失败 ", i, idx)
					return 0
				}

				idx += n
			}
		default:
			log.Println("readArray 不技能的数组类型 ", fld.elemKind)
			return 0
		}
	}
	return idx
}

type PByteArray (*[cMaxArrSize]byte)
type PStrArray (*[cMaxArrSize]string)

// 获取切片的长度
func getSliceLength(ptr uintptr) int {
	return (*(*reflect.SliceHeader)(unsafe.Pointer(ptr))).Len
}

func getSliceDataPtr(ptr uintptr) uintptr {
	return (*(*reflect.SliceHeader)(unsafe.Pointer(ptr))).Data
}

// 计算切片的写入长度
func getSliceWriteLen(ptr uintptr, fld *fieldInfo) uint32 {
	len := getSliceLength(ptr)
	writeLen := GetLengthDataLen(uint32(len))
	if fld.elemSize > 0 {
		writeLen += uint32(len) * fld.elemSize
	} else {
		switch fld.elemKind {
		case reflect.String:
			ps := (*[]string)(unsafe.Pointer(ptr))
			for i := 0; i < len; i++ {
				writeLen += getStringWriteLen((*ps)[i])
			}
		default:
			log.Println("不支持的字段切片类型计算长度 ", fld.elemType)
			return 0
		}
	}
	return writeLen
}

func getArrayWriteLen(ptr uintptr, fld *fieldInfo) uint32 {
	writeLen := uint32(0)
	switch fld.elemKind {
	case reflect.String:
		psArr := (PStrArray)(unsafe.Pointer(ptr))
		for i := 0; i < int(fld.arrLen); i++ {
			writeLen += getStringWriteLen((*psArr)[i])
		}
	default:
		log.Println("不支持的数组类型计算长度，类型=", fld.elemType)
		return 0
	}
	return writeLen
}

// 计算动态字段的长度
func (pInfo *typeInfo) calcDataSize(valuePtr uintptr) uint32 {
	// log.Println("calcDataSize: ", len(pInfo.fields), *pInfo)
	fldLen := len(pInfo.dynFields)
	var result uint32 = pInfo.fixedSize
	for i := 0; i < fldLen; i++ {
		fld := &pInfo.dynFields[i]
		addr := valuePtr + fld.offset
		// log.Println("calcDataSize: ", pInfo.tp, i, fld.kind)
		switch fld.kind {
		case reflect.String:
			result += getStringWriteLen(*(*string)(unsafe.Pointer(addr)))

		case reflect.Slice:
			result += getSliceWriteLen(addr, fld)

		case reflect.Array:

			result += getArrayWriteLen(addr, fld)

		case reflect.Struct: // 结构递归运算
			// log.Println("calcDataSize, offset = ", fld.offset)
			result += fld.structInfo.calcDataSize(addr)

		default:
			log.Println("未处理的类型 ", fld.kind, pInfo.tp.Name())
			return 0
		}
	}

	// log.Println("calcDataSize: result = ", result)
	return result
}

func (s *Serializer) tryGetTypeInfo(tp reflect.Type) (atpInfo *typeInfo, ret bool) {
	s.mu.RLock()
	defer s.mu.RUnlock()
	tpInfo, ok := s.typeHashTable[tp]
	return tpInfo, ok
}

func (s *Serializer) getTypeInfo(tp reflect.Type) (atpInfo *typeInfo, isOk bool) {

	tpInfo, ok := s.tryGetTypeInfo(tp)
	if !ok {
		tpInfo = s.regType(0, tp) // 找不到就直接注册一个
	}
	return tpInfo, tpInfo != nil
}

func (s *Serializer) encodeStruct(bits []byte, valuePtr uintptr, tpInfo *typeInfo) uint32 {
	// log.Println("encodeStruct: ", valuePtr, bits, *tpInfo)

	idx := uint32(0)

	for i := 0; i < len(tpInfo.fields); i++ {
		fld := &(tpInfo.fields[i])
		fldAddr := valuePtr + fld.offset
		if fld.size > 0 {
			ps := unsafe.Pointer(fldAddr)
			pd := unsafe.Pointer(&bits[idx])
			switch fld.size { // 下面这种写法能提升10%的速度
			case 1:
				bits[idx] = *(*uint8)(ps)
			case 2:
				*(*uint16)(pd) = *(*uint16)(ps)
			case 4:
				*(*uint32)(pd) = *(*uint32)(ps)
			case 8:
				*(*uint64)(pd) = *(*uint64)(ps)
			case 16:
				*(*complex128)(pd) = *(*complex128)(ps)
			default:
				Move(fldAddr, uintptr(pd), fld.size)
			}
			idx += fld.size
		} else {
			switch fld.kind {
			case reflect.String:
				str := *(*string)(unsafe.Pointer(fldAddr))
				n := WriteString(bits[idx:], str)
				idx += n

			case reflect.Slice:
				n := writeSlice(bits[idx:], fldAddr, fld)
				idx += n

			case reflect.Array:
				n := writeArray(bits[idx:], fldAddr, fld)
				idx += n

			case reflect.Struct:
				n := s.encodeStruct(bits[idx:], fldAddr, fld.structInfo)
				idx += n

			default:
				log.Println("EncodeStruct 不支持的字段类型： ", fld.kind)
				return 0
			}
		}
	}

	// log.Println("encode: len = ", idx)
	return idx
}

// 根据注册ID新建结构，方便外面使用
func (s *Serializer) NewStruct(id HashIdType) interface{} {
	info, isOk := s.idHashTable[id]
	if isOk {
		v := reflect.New(info.tp)
		return v.Interface()
	}
	return nil
}

// 这里传指针，加快访问速度，不用注册，没类型会自动注册，如果是网络协议中就要先注册
func (s *Serializer) Encode(ptr interface{}) (result []byte, ok bool) {
	value := reflect.ValueOf(ptr)
	if value.Type().Kind() != reflect.Ptr {
		log.Println("编码只能传指针， 为了提高效率", value.Type())
		return nil, false
	}

	value = reflect.Indirect(value)

	tpInfo, ok := s.getTypeInfo(value.Type())
	if !ok {
		log.Println("找不到类型信息，应该没有注册")
		return nil, false
	}

	valuePtr := GetValueDataPtr(&value)

	allSize := tpInfo.calcDataSize(valuePtr)
	// log.Println("写入结构总长度为: ", allSize)

	idx := uint32(0)
	var bits []byte

	if !s.isLikeCRecord {
		n := GetLengthDataLen(allSize)

		bits = make([]byte, cCRC32Size+n+allSize) // 开始要写CRC+len

		*(*uint32)(unsafe.Pointer(&bits[idx])) = tpInfo.crc32
		idx += cCRC32Size

		WiriteLength(bits[idx:], allSize) // 写入总长度
		idx += n
	} else {
		bits = make([]byte, allSize)
	}

	// log.Println("Encode: idx = ", idx)

	writeLen := s.encodeStruct(bits[idx:], valuePtr, tpInfo)

	// log.Println("Encode: writeLen = ", writeLen, allSize)
	if writeLen != allSize {
		return nil, false
	} else {
		return bits, true
	}
}

func (s *Serializer) decodeStruct(bits []byte, valuePtr uintptr, tpInfo *typeInfo) uint32 {
	bitsLen := uint32(len(bits))
	idx := uint32(0)

	for i := 0; i < len(tpInfo.fields); i++ {
		fld := &(tpInfo.fields[i])
		fldAddr := valuePtr + fld.offset
		pBytes := PByteArray(unsafe.Pointer(fldAddr))
		if fld.size > 0 {
			if idx+fld.size > bitsLen {
				log.Println("decodeStruct: 读取字段失败 ", i, *fld, *tpInfo)
				return 0
			}
			switch fld.size { // 下面这种写法能提升10%的速度
			case 1:
				pBytes[0] = bits[idx]
			case 2:
				*(*uint16)(unsafe.Pointer(pBytes)) = *(*uint16)(unsafe.Pointer(&bits[idx]))
			case 4:
				*(*uint32)(unsafe.Pointer(pBytes)) = *(*uint32)(unsafe.Pointer(&bits[idx]))
			case 8:
				*(*uint64)(unsafe.Pointer(pBytes)) = *(*uint64)(unsafe.Pointer(&bits[idx]))
			case 16:
				*(*complex128)(unsafe.Pointer(pBytes)) = *(*complex128)(unsafe.Pointer(&bits[idx]))
			default:
				copy(pBytes[0:fld.size], bits[idx:])
			}
			idx += fld.size
		} else {
			switch fld.kind {
			case reflect.String:
				str, n := ReadString(bits[idx:])
				if n == 0 {
					log.Println("读取字符串字段失败: ", idx, bits, tpInfo.tp, fld)
					return 0
				}
				idx += n
				*(*string)(unsafe.Pointer(pBytes)) = str

			case reflect.Slice:
				n := readSlice(bits[idx:], fldAddr, fld)
				if n == 0 {
					log.Println("读取Slice字段失败: ", fld)
					return 0
				}
				idx += n

			case reflect.Array:
				n := readArray(bits[idx:], fldAddr, fld)
				if n == 0 {
					log.Println("读取array字段失败", fld)
					return 0
				}
				idx += n

			case reflect.Struct:
				n := s.decodeStruct(bits[idx:], fldAddr, fld.structInfo)
				if n == 0 {
					log.Println("读取struct字段失败", idx, tpInfo.tp, fld.structInfo)
					return 0
				}
				idx += n

			default:
				log.Println("DecodeStruct 不支持的字段类型： ", fld.kind)
				return 0
			}
		}
	}

	return idx
}

func (s *Serializer) Decode(bits []byte, ptr interface{}) bool {
	value := reflect.ValueOf(ptr)
	tp := value.Type()
	if tp.Kind() != reflect.Ptr {
		log.Println("解码只能传指针，否则读不到内容 ", tp)
		return false
	}

	value = reflect.Indirect(value) // 指针转值
	tp = value.Type()

	bitsLen := uint32(len(bits))

	var minHeaderSize = cMinHeaderSize
	if s.isLikeCRecord {
		minHeaderSize = 0
	} else if bitsLen < cMinHeaderSize {
		log.Println("Decode: 解码长度小于最小头部长度", bitsLen, cMinHeaderSize)
		return false
	}

	tpInfo, ok := s.getTypeInfo(tp)
	if !ok {
		fmt.Println("找不到类型信息，应该没有注册")
		return false
	}

	if bitsLen < tpInfo.fixedSize+minHeaderSize {
		log.Println("bitslen 小于结构体固定大小 ", bitsLen, tpInfo.fixedSize)
		return false
	}

	valuePtr := GetValueDataPtr(&value)

	idx := uint32(0)

	if !s.isLikeCRecord {
		crc32 := *(*uint32)(unsafe.Pointer(&bits[idx]))
		idx += cCRC32Size
		if crc32 != tpInfo.crc32 {
			log.Println("Decode: crc32 不一致 ", crc32, tpInfo.crc32, tpInfo.tp)
			return false
		}

		l, n := ReadLength(bits[idx:])
		if n == 0 {
			log.Println("Decode: 读取长度失败")
			return false
		}

		idx += n

		if idx+l != bitsLen {
			log.Println("Decode: all 剩余长度不对: ", idx, l, bitsLen)
			return false
		}
	}

	decodeLen := s.decodeStruct(bits[idx:], valuePtr, tpInfo)
	// log.Println("Decode: ", decodeLen, bitsLen)
	return decodeLen+idx == bitsLen
}

func (s *Serializer) DecodeStruct(id HashIdType, bits []byte) (obj interface{}, isOk bool) {
	obj = s.NewStruct(id)
	if obj != nil {
		if s.Decode(bits, obj) {
			return obj, true
		}
	}
	return nil, false
}
